home *** CD-ROM | disk | FTP | other *** search
- Subject: v18i058: Find files using C-style expressions
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Kenneth Stauffer <stauffer@cpsc.UCalgary.CA>
- Posting-number: Volume 18, Issue 58
- Archive-name: rh
-
- Rh, was written by Ken Stauffer to make the job of finding files easier by
- allowing the user to enter real C expressions. This notation is much
- easier to master than the notation used by the Unix find(1) command,
- partly because most Unix users already know C and party because the syntax
- is more consistant. In addition to being easier to use than find(1), its
- expressions can be used to select a more diverse subset of files.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: README Makefile rh.h rh.c rhcmds.c rhdir.c rhparse.c
- # rh.man sample
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(3050 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X March 6, 1989
- X
- XINTRODUCTION:
- XRh, was written by Ken Stauffer (c)1989, to make the
- Xjob of finding files easier by allowing the
- Xuser to enter real C expressions. This notation is
- Xmuch easier to master than the notation used by the
- XUnix find(1) command, partly because most Unix users
- Xalready know C and party because the syntax is more
- Xconsistant. In addition to being easier to use
- Xthan find(1), its expressions can be used to select
- Xa more diverse subset of files.
- X
- XPORTABILITY:
- XIn the makefile the user must specify what flavour of unix
- Xthey are making rh for. For the most part rh is portable
- Xto all unix systems, except for the portion of code
- Xthat does the directory reading. The code that does this
- Xhas been isolated in the file 'rhdir.c'. There are two basic
- Xmechanisms I have seen for directory reading:
- X
- X XENIX / SYSV:
- X ------------
- X This method simply opens the directory as a file
- X and does fread()'s to grab the directory entries. This is
- X the simplest and most obvious way. However on BSD systems
- X a library routine is placed between the programmer and
- X the system call interface for portablility reasons.
- X
- X BSD:
- X ---
- X Berkley adds the readdir() routine. Which has
- X its own data type, DIR which is used for the
- X reading of directories. However the structure to which these
- X entries are placed is still 'struct direct'. This again differs
- X from the SUN implementation.
- X
- X SUN:
- X ---
- X Sun OS, is similar to BSD except that an include
- X file is different, and also it uses a 'struct dirent'
- X instead of 'struct direct'.
- X
- X All of these differences have been taken into account in
- X the file 'rhdir.c', and hopefully will work on your system.
- X So far 'rh' works on:
- X SCO XENIX, VAX (BSD 4.3) and SUN 4's (and SUN 3's).
- X
- X If your system is different from the ones above, then
- X the modifications should be made to 'rhdir.c' ONLY.
- X
- XCOMPILING:
- XTo make rh work on your system, the file Makefile must be
- Xedited to match your system. There is a single '-D' option
- Xthat must be changed in the Makefile. Define ONE of the
- Xfollowing in the definition of CFLAGS:
- X
- X -DBSD - This would be used for
- X most BSD systems. (VAX's)
- X -DSUN - This would be used for
- X SUN computers. (SUN 4 / SUN 3)
- X -DXENIX - Xenix systems. (Tandy 6000)
- X -DSYSV - System V systems.
- X
- XIn addition to the C source there is also a file called
- Xrh.man. This is a nroff file and can be created by a command like:
- X nroff -man rh.man > rh.cat
- XThe resultant file (rh.cat) is sutable for general viewing.
- X
- XFinally there is a file called sample. This file contains some
- Xsample rh expressions. To use them the user can type:
- X
- X % rh -l -f sample -mex1
- X
- XThis would do a search of the current working directory, and
- Xuse the expression 'ex1' from the file 'sample'.
- X
- XOnce rh is made, you can do what you want with it. A good test to
- Xsee if it is working is to do a:
- X
- X % rh -la -e 1 /
- X
- XThis will find all files that makes the constant exression '1' true.
- XSo unless your not root, all files on the system will be printed.
- X
- XKen Stauffer.
- X
- XI can be reached via email at:
- X root@sixk
- END_OF_FILE
- if test 3050 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(530 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X# rh:
- X# (c) 1989 Ken Stauffer
- X#
- X# Place one of the following -D's onto the end of
- X# the definition of CFLAGS.
- X#
- X# -DXENIX
- X# - xenix like OS
- X#
- X# -DSYSV
- X# - System V/III like OS
- X#
- X# -DBSD
- X# - BSD like OS
- X#
- X# -DSUN
- X# - SUN OS
- X#
- X
- XCFLAGS= -DXENIX -O -n
- X
- Xrh: rhcmds.o rh.o rhparse.o rhdir.o
- X cc $(CFLAGS) -o rh rh.o rhcmds.o rhparse.o rhdir.o
- X
- Xrhdir.o: rhdir.c rh.h
- X cc $(CFLAGS) -c rhdir.c
- X
- Xrh.o: rh.c rh.h
- X cc $(CFLAGS) -c rh.c
- X
- Xrhcmds.o: rhcmds.c rh.h
- X cc $(CFLAGS) -c rhcmds.c
- X
- Xrhparse.o: rhparse.c rh.h
- X cc $(CFLAGS) -c rhparse.c
- X
- END_OF_FILE
- if test 530 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'rh.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rh.h'\"
- else
- echo shar: Extracting \"'rh.h'\" \(4290 characters\)
- sed "s/^X//" >'rh.h' <<'END_OF_FILE'
- X
- X/* ----------------------------------------------------------------------
- X * FILE: rh.h
- X * (c) 1989 Ken Stauffer
- X * This header contains the #define's for the tokens.
- X * It also contains the initialized arrays. By having
- X * rh.c define a symbol MAIN, the space is allocated for these globals
- X * only once.
- X *
- X * ---------------------------------------------------------------------- */
- X
- X#include <stdio.h>
- X
- X#define START 256
- X#define OR 256 /* || */
- X#define AND 257 /* && */
- X#define LE 258 /* <= */
- X#define LT 259 /* < */
- X#define GE 260 /* >= */
- X#define GT 261 /* > */
- X#define NE 262 /* != */
- X#define EQ 263 /* == */
- X#define BOR 264 /* | */
- X#define BAND 265 /* & */
- X#define BXOR 266 /* ^ */
- X#define NOT 267 /* ! */
- X#define PLUS 268 /* + */
- X#define MUL 269 /* * */
- X#define MINUS 270 /* - */
- X#define DIV 271 /* / */
- X#define MOD 272 /* % */
- X#define BNOT 273 /* ~ */
- X#define UNIMINUS 274 /* - */
- X#define SHIFTL 275 /* << */
- X#define SHIFTR 276 /* >> */
- X#define QM 277 /* ? */
- X#define COLON 278 /* : */
- X#define NOP 279 /* */
- X
- X#define NUMBER 280 /* eg. 1234,NOW,IFDIR */
- X#define STAR 281 /* eg. "*.BAK" */
- X#define FIELD 282 /* mode, uid */
- X#define MACRONAME 283
- X#define UNKNOWN 284
- X
- X#define NOW_INDEX 1 /* where to place the current time */
- X#define MACRO_INDEX 0 /* where the macro name goes */
- X
- X#define LENGTH 100 /* size of stack program */
- X#define MEM 20 /* size of stack */
- X#define IDLENGTH 20
- X#define STARLEN 1000 /* total chars available for strings */
- X
- X#if BSD || SUN
- X#define DEPTH getdtablesize()
- X#endif
- X
- X#if XENIX || SYSV
- X/* This value was arbitrarily chosen */
- X#define DEPTH 24
- X#endif
- X
- Xstruct instr {
- X int i_type;
- X long i_value;
- X};
- X
- X#ifdef MAIN
- X
- Xextern c_or(), c_and(), c_le(), c_lt(), c_ge(),
- X c_gt(), c_ne(), c_eq(), c_bor(), c_band(),
- X c_bxor(), c_not(), c_plus(), c_mul(), c_minus(),
- X c_div(), c_mod(), c_number(), c_atime(), c_ctime(),
- X c_dev(), c_gid(), c_ino(), c_mode(), c_mtime(),
- X c_nlink(), c_rdev(), c_size(), c_uid(), c_star(),
- X c_bnot(), c_uniminus(), c_lshift(), c_rshift(), c_qm(),
- X c_colon(), c_nop();
- X
- X#if SUN || BSD
- Xchar *identifiers[]={ "", "NOW" , "IFBLK", "IFCHR", "IFDIR", "IFLNK", "IFMT",
- X "IFREG", "IFSOCK", "ISGID", "ISUID", "ISVTX",
- X "atime", "ctime", "dev", "gid", "ino",
- X "mode", "mtime", "nlink", "rdev", "size", "uid",
- X NULL };
- X
- Xlong constants[]={ 0,0,
- X S_IFBLK, S_IFCHR, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, S_IFSOCK,
- X S_ISGID, S_ISUID, S_ISVTX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- X#endif
- X
- X#if XENIX || SYSV
- Xchar *identifiers[]={ "", "NOW", "IFBLK", "IFCHR", "IFDIR", "IFMT",
- X "IFREG", "IFIFO", "ISGID", "ISUID", "ISVTX",
- X "atime", "ctime", "dev", "gid", "ino",
- X "mode", "mtime", "nlink", "rdev", "size", "uid",
- X NULL };
- X
- Xlong constants[]={ 0,0,
- X S_IFBLK, S_IFCHR, S_IFDIR, S_IFMT, S_IFREG, S_IFIFO,
- X S_ISGID, S_ISUID, S_ISVTX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- X#endif
- X
- Xint (*commands[])()= {
- X c_or, c_and, c_le, c_lt, c_ge,
- X c_gt, c_ne, c_eq, c_bor, c_band,
- X c_bxor, c_not, c_plus, c_mul, c_minus,
- X c_div, c_mod, c_bnot, c_uniminus,c_lshift,
- X c_rshift, c_qm, c_colon, c_nop, c_number,
- X c_star, c_atime, c_ctime, c_dev, c_gid,
- X c_ino, c_mode, c_mtime, c_nlink, c_rdev,
- X c_size, c_uid };
- X
- X long tokenval;
- X long token;
- X
- X struct instr StackProgram[ LENGTH ];
- X int PC;
- X
- X long Stack[ MEM ];
- X int SP;
- X
- X struct stat *globuf;
- X char *fname;
- X int dashf;
- X int dashl;
- X int dashe;
- X int dashr;
- X int dashh;
- X int dashm;
- X int dasha;
- X char *expstr;
- X FILE *expfile;
- X
- X char Starbuf[ STARLEN ];
- X int starfree=0;
- X
- X#else
- X extern long constants[];
- X extern char *identifiers[];
- X extern int (*commands[])();
- X
- X extern long tokenval;
- X extern long token;
- X extern struct instr StackProgram[];
- X extern int PC;
- X extern long Stack[];
- X extern int SP;
- X extern struct stat *globuf;
- X extern char *fname;
- X extern char Starbuf[];
- X extern int starfree;
- X extern int dashf;
- X extern int dashl;
- X extern int dashe;
- X extern int dashr;
- X extern int dashh;
- X extern int dashm;
- X extern int dasha;
- X extern char *expstr;
- X extern FILE *expfile;
- X#endif
- END_OF_FILE
- if test 4290 -ne `wc -c <'rh.h'`; then
- echo shar: \"'rh.h'\" unpacked with wrong size!
- fi
- # end of 'rh.h'
- fi
- if test -f 'rh.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rh.c'\"
- else
- echo shar: Extracting \"'rh.c'\" \(5063 characters\)
- sed "s/^X//" >'rh.c' <<'END_OF_FILE'
- X
- X/* ----------------------------------------------------------------------
- X * FILE: rh.c
- X * (c) 1989 Ken Stauffer
- X *
- X * printhelp(), execute(), examine(), main()
- X *
- X *
- X * ---------------------------------------------------------------------- */
- X
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#define MAIN
- X#include "rh.h"
- X
- Xstatic char usage[]={
- X"Usage: %s [-ahlr] [ [-e expr] | [-f filename [-mname]] ] file ...\n"
- X};
- X
- X
- X/* ----------------------------------------------------------------------
- X * printhelp:
- X * Print out the help screen. The string 's' is argv[0].
- X * Called when the -h option is used.
- X *
- X */
- X
- Xprinthelp(s)
- Xchar *s;
- X{
- X int i;
- X
- X printf(usage,s);
- X printf("options:\n");
- X printf("\t-h show this message\n");
- X printf("\t-l long filename output\n");
- X printf("\t-r makes %s non-recursive\n",s);
- X printf("\t-a adds to the long output to make it longer\n");
- X printf("\t-mname use the named macro 'name' from 'file'\n");
- X printf("\t-e get expression from the command line\n");
- X printf("\t-f get expression from file\n\n");
- X printf("VALID EXPRESSIONS CONSIST OF:\n");
- X
- X printf("\tCONSTANTS/variables: see stat(2)\n");
- X for(i=0; identifiers[i]; i++ )
- X printf("%s%12s%s", (!(i%5==0)) ? "\t" : "" ,
- X identifiers[i],
- X (i%5==4 || !identifiers[i+1]) ? "\n" : " ");
- X
- X printf("\tC OPERATORS (precedence same as C):\n");
- X printf("\t! ~ - * / %% + < <= > >= == != & ^ | << >> && || ?:\n");
- X printf("\tSPECIAL OPERATORS:\n");
- X printf("\t$username , \"*.c\" , [yyyy/mm/dd]\n\n");
- X
- X}
- X
- X/* ----------------------------------------------------------------------
- X * execute:
- X * Execute the program contained in the StackProgram[]
- X * array.
- X * Indexes the commands[] array to obtain the correct
- X * function/operator. Programs are NULL terminated.
- X * Returns the result of the expression.
- X *
- X */
- X
- Xexecute()
- X{
- X register long etype,eval;
- X SP=0;
- X for(PC=0; (etype=StackProgram[PC].i_type) ; PC++) {
- X eval=StackProgram[PC].i_value;
- X
- X (*commands[ (etype!=FIELD) ? etype-START : etype-START+eval ] ) (eval);
- X
- X }
- X return( Stack[0] );
- X}
- X
- X/* ----------------------------------------------------------------------
- X * examine:
- X * This function is called for every file that 'rh' examines.
- X * examine() first calls execute to see if the
- X * expression is true, it then prints the file if the expression
- X * evaluated to true (non-zero).
- X *
- X */
- X
- Xexamine(s,buf)
- Xchar *s;
- Xstruct stat *buf;
- X{
- X fname=s;
- X globuf=buf;
- X
- X if( execute() )
- X (dashl) ? printentry(globuf,fname) : printf("%s\n",fname);
- X}
- X
- X/* ----------------------------------------------------------------------
- X * main:
- X * parse arguments.
- X * two for loops are used to parse the argument list,
- X * the first for loop process the arguments. The second
- X * for loop process the characters within the current argument.
- X * -l, -r, -h options can occur as often as desired.
- X * -f and -e and -m can only occur once and MUST have an argument.
- X *
- X * parse expression.
- X * the expression is parsed and if all is ok, then the
- X * recursive hunt is started.
- X *
- X */
- X
- Xmain(argc,argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i,r,skip;
- X char *j;
- X
- X /* defaults */
- X dashe = 0; /* -e option */
- X dashl = 0; /* -l */
- X dashf = 0; /* -f */
- X dashr = 1; /* -r */
- X dashh = 0; /* -h */
- X dashm = 0; /* -m */
- X dasha = 0; /* -a */
- X
- X for(i=1; i<argc; i++ ) {
- X if( *argv[i] != '-' ) break;
- X skip = 0;
- X for(j=argv[i]+1; *j; j++ ) {
- X switch( *j ) {
- X case 'l': dashl = 1; break;
- X case 'r': dashr = 0; break;
- X case 'h': dashh = 1; break;
- X case 'a': dashl = dasha = 1; break;
- X case 'm':
- X if( dashm ) {
- X fprintf(stderr,"%s: too many -m options\n", argv[0]);
- X exit(-1);
- X }
- X dashm = 1;
- X identifiers[ MACRO_INDEX ] = j+1;
- X while(*j) j++; j--;
- X break;
- X case 'e':
- X if( dashe ) {
- X fprintf(stderr, "%s: too many -e options\n",argv[0]);
- X exit(-1);
- X }
- X dashe = i+1;
- X skip = 1;
- X break;
- X case 'f':
- X if( dashf ) {
- X fprintf(stderr, "%s: too many -f options\n",argv[0]);
- X exit(-1);
- X }
- X dashf = i+1;
- X skip = 1;
- X break;
- X default:
- X fprintf(stderr,"%s: illegal option -%c, use -h for help\n",
- X argv[0],*j);
- X fprintf(stderr,usage, argv[0]);
- X exit(-1);
- X }
- X if( dashf && dashe ) {
- X fprintf(stderr, "%s: cannot have both -e and -f\n",argv[0]);
- X exit(-1);
- X }
- X }
- X if( skip ) i++;
- X }
- X
- X if( dashh ) printhelp(argv[0]);
- X
- X if( dashm && !dashf ) {
- X fprintf(stderr,"%s: -m option needs the -f option\n",argv[0]);
- X exit(-1);
- X }
- X if( dashf >= argc ) {
- X fprintf(stderr,"%s: -f missing an argument\n",argv[0]);
- X exit(-1);
- X }
- X if( dashe >= argc ) {
- X fprintf(stderr,"%s: -e missing an argument\n",argv[0]);
- X exit(-1);
- X }
- X
- X if( dashe ) { expstr = argv[dashe]; }
- X else if( dashf ) {
- X expstr = argv[dashf];
- X if( (expfile = fopen(expstr,"r")) == NULL ) {
- X fprintf(stdout,"%s: cannot open %s\n",
- X argv[0],expstr);
- X exit(-1);
- X }
- X } else expfile = stdin;
- X
- X expression();
- X
- X if( i >= argc ) {
- X r=ftw(".",examine,(dashr)? DEPTH :1);
- X if(r == -1) perror(".");
- X } else
- X for(; i<argc; i++) {
- X r=ftw( argv[i],examine,(dashr)? DEPTH :1);
- X if( r == -1 ) perror(argv[i]);
- X }
- X}
- END_OF_FILE
- if test 5063 -ne `wc -c <'rh.c'`; then
- echo shar: \"'rh.c'\" unpacked with wrong size!
- fi
- # end of 'rh.c'
- fi
- if test -f 'rhcmds.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rhcmds.c'\"
- else
- echo shar: Extracting \"'rhcmds.c'\" \(3879 characters\)
- sed "s/^X//" >'rhcmds.c' <<'END_OF_FILE'
- X
- X/* ----------------------------------------------------------------------
- X * FILE: rhcmds.c
- X * (c) 1989 Ken Stauffer
- X * This file contains the functions that do the evaluation of
- X * the stack program.
- X * These functions are simple, and behave like RPN operators, that is
- X * they use the last two values on that stack, apply an operator
- X * and push the result. Similarly for unary ops.
- X *
- X * ---------------------------------------------------------------------- */
- X
- X#include "rh.h"
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- Xc_or(i) long i; { Stack[SP-2]=Stack[SP-2] || Stack[SP-1]; SP--; }
- Xc_and(i) long i; { Stack[SP-2]=Stack[SP-2] && Stack[SP-1]; SP--; }
- Xc_le(i) long i; { Stack[SP-2]=Stack[SP-2] <= Stack[SP-1]; SP--; }
- Xc_lt(i) long i; { Stack[SP-2]=Stack[SP-2] < Stack[SP-1]; SP--; }
- Xc_ge(i) long i; { Stack[SP-2]=Stack[SP-2] >= Stack[SP-1]; SP--; }
- Xc_gt(i) long i; { Stack[SP-2]=Stack[SP-2] > Stack[SP-1]; SP--; }
- Xc_ne(i) long i; { Stack[SP-2]=Stack[SP-2] != Stack[SP-1]; SP--; }
- Xc_eq(i) long i; { Stack[SP-2]=Stack[SP-2] == Stack[SP-1]; SP--; }
- Xc_bor(i) long i; { Stack[SP-2]=Stack[SP-2] | Stack[SP-1]; SP--; }
- Xc_band(i) long i; { Stack[SP-2]=Stack[SP-2] & Stack[SP-1]; SP--; }
- Xc_bxor(i) long i; { Stack[SP-2]=Stack[SP-2] ^ Stack[SP-1]; SP--; }
- Xc_plus(i) long i; { Stack[SP-2]=Stack[SP-2] + Stack[SP-1];SP--; }
- Xc_mul(i) long i; { Stack[SP-2]=Stack[SP-2] * Stack[SP-1]; SP--; }
- Xc_minus(i)long i; { Stack[SP-2]=Stack[SP-2] - Stack[SP-1]; SP--; }
- Xc_div(i) long i; { Stack[SP-2]=Stack[SP-2] / Stack[SP-1]; SP--; }
- Xc_mod(i) long i; { Stack[SP-2]=Stack[SP-2] % Stack[SP-1]; SP--; }
- Xc_lshift(i) long i; { Stack[SP-2]=Stack[SP-2] << Stack[SP-1]; SP--; }
- Xc_rshift(i) long i; { Stack[SP-2]=Stack[SP-2] >> Stack[SP-1]; SP--; }
- X
- X/* unary instructions */
- X
- Xc_not(i) long i; { Stack[SP-1]= ! Stack[SP-1]; }
- Xc_bnot(i) long i; { Stack[SP-1]= ~ Stack[SP-1]; }
- Xc_uniminus(i) long i; { Stack[SP-1]= - Stack[SP-1]; }
- X
- X/* trinary operator ?: */
- X
- Xc_qm(i) long i; { PC = (Stack[SP-1]) ? PC : i; SP--; }
- Xc_colon(i) long i; { PC = i; }
- Xc_nop(i) long i; { }
- X
- X/* operand functions */
- X
- Xc_number(i) long i; { Stack[SP++] = i; }
- Xc_atime(i) long i; { Stack[SP++] = globuf->st_atime; }
- Xc_ctime(i) long i; { Stack[SP++] = globuf->st_ctime; }
- Xc_dev(i) long i; { Stack[SP++] = globuf->st_dev; }
- Xc_gid(i) long i; { Stack[SP++] = globuf->st_gid; }
- Xc_ino(i) long i; { Stack[SP++] = globuf->st_ino; }
- Xc_mode(i) long i; { Stack[SP++] = globuf->st_mode; }
- Xc_mtime(i) long i; { Stack[SP++] = globuf->st_mtime; }
- Xc_nlink(i) long i; { Stack[SP++] = globuf->st_nlink; }
- Xc_rdev(i) long i; { Stack[SP++] = globuf->st_rdev; }
- Xc_size(i) long i; { Stack[SP++] = globuf->st_size; }
- Xc_uid(i) long i; { Stack[SP++] = globuf->st_uid; }
- X
- X
- X/* ----------------------------------------------------------------------
- X * star:
- X * This implements the trivial regular expression stuff.
- X * Since people may want to upgrade this, I will explain the
- X * parameter. 'i' is an index into the array Startbuf[]. The
- X * string contained there is the actual '\0' terminated
- X * string that occured in the expression (eg "*.BAK" ), minus
- X * the "'s.
- X * The reasons for the simplistic regular expressions is
- X * because it was easy, because lots of unix systems do
- X * regexp() in lots of ways and this method is fairly fast.
- X *
- X */
- X
- Xc_star(i)
- Xlong i;
- X{
- X
- X register int ri,ii;
- X
- X if( Starbuf[i]=='*') {
- X ii=strlen(fname)-1;
- X ri=strlen(Starbuf+i)-1+i;
- X while( fname[ii]==Starbuf[ri] && ri>i ) {
- X ri--; ii--;
- X }
- X Stack[SP++] = (ri==i);
- X }
- X else {
- X int x=0;
- X ii=0;
- X while( fname[x] ) {
- X if(fname[x]=='/') ii=x;
- X x++;
- X }
- X ii++;
- X ri=i;
- X while( fname[ii]==Starbuf[ri] && Starbuf[ri]!='*'
- X && fname[ii] && Starbuf[ri]) {
- X ri++; ii++;
- X }
- X Stack[SP++]=!(fname[ii]+Starbuf[ri]) || Starbuf[ri]=='*';
- X }
- X}
- X
- END_OF_FILE
- if test 3879 -ne `wc -c <'rhcmds.c'`; then
- echo shar: \"'rhcmds.c'\" unpacked with wrong size!
- fi
- # end of 'rhcmds.c'
- fi
- if test -f 'rhdir.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rhdir.c'\"
- else
- echo shar: Extracting \"'rhdir.c'\" \(5549 characters\)
- sed "s/^X//" >'rhdir.c' <<'END_OF_FILE'
- X
- X/* ----------------------------------------------------------------------
- X * FILE: rhdir.c
- X * (c) 1989 Ken Stauffer
- X * This file contains the "non portable" stuff dealing with
- X * directories.
- X * printentry(), ftw(), ftw1()
- X *
- X *
- X * ---------------------------------------------------------------------- */
- X
- X#include "rh.h"
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X#define user_index(b) ((000777 & b) >> 6) + (b & S_ISUID ? 8 : 0)
- X#define group_index(b) ((000077 & b) >> 3) + (b & S_ISGID ? 8 : 0)
- X#define all_index(b) ((000007 & b) + ((b & S_ISVTX) ? 8 : 0))
- X#define ftype_index(b) (b >> 13)
- X
- X#define isdirect(b) ((b&S_IFMT)==S_IFDIR)
- X
- X#if SUN
- X
- X#include <dirent.h>
- X#define MAXPATHLEN 255
- X#define islink(b) ((b & S_IFLNK) == S_IFLNK)
- X#define isproper(m) ( isdirect(m) && !(((m)&S_IFLNK)==S_IFLNK) )
- X
- X#endif
- X
- X#if BSD
- X
- X#include <sys/dir.h>
- X#define MAXPATHLEN 255
- X#define islink(b) ((b & S_IFLNK) == S_IFLNK)
- X#define isproper(m) ( isdirect(m) && !(((m)&S_IFLNK)==S_IFLNK) )
- X
- X#endif
- X
- X#if XENIX || SYSV
- X
- X#include <sys/dir.h>
- X#define MAXPATHLEN 255
- X#define islink(b) (0)
- X#define isproper(m) isdirect(m)
- X#define lstat stat
- X
- X#endif
- X
- X
- Xstatic int (*func)();
- Xstatic char filename[ MAXPATHLEN ];
- X
- X/* ----------------------------------------------------------------------
- X * printentry:
- X * Display filename,permissions and size in a '/bin/ls' like
- X * format. Examines the dasha variable to see if more
- X * info should be printed.
- X * uses the macros:
- X * user_index(b)
- X * group_index(b)
- X * all_index(b)
- X * ftype_index(b)
- X *
- X */
- X
- Xprintentry(buf,name)
- Xstruct stat *buf;
- Xchar *name;
- X{
- X char *t,*ctime();
- X
- X static char *ftype[]={ "p", "c" ,
- X "d" , "b" ,
- X "-" , "l" ,
- X "s" , "t" };
- X
- X static char *perm[]={ "---", "--x", "-w-", "-wx" ,
- X "r--", "r-x", "rw-", "rwx" ,
- X "--S", "--s", "-wS", "-ws" ,
- X "r-S", "r-s", "rwS", "rws" };
- X
- X static char *perm2[]={ "---", "--x", "-w-", "-wx" ,
- X "r--", "r-x", "rw-", "rwx" ,
- X "--T", "--t", "-wT", "-wt" ,
- X "r-T", "r-t", "rwT", "rwt" };
- X
- X if( dasha ) {
- X t = ctime(&buf->st_mtime);
- X t[24] = '\0';
- X printf("%s%s%s%s %4d %4d %6d %s %-s\n",
- X ftype[ ftype_index(buf->st_mode) ],
- X perm[ user_index(buf->st_mode) ],
- X perm[ group_index(buf->st_mode) ],
- X perm2[ all_index(buf->st_mode) ],
- X buf->st_uid,
- X buf->st_gid,
- X buf->st_size,
- X t+4,
- X name );
- X } else {
- X printf("%s%s%s%s %9d %-s\n",
- X ftype[ ftype_index(buf->st_mode) ],
- X perm[ user_index(buf->st_mode) ],
- X perm[ group_index(buf->st_mode) ],
- X perm2[ all_index(buf->st_mode) ],
- X buf->st_size,
- X name );
- X }
- X}
- X
- X/* ----------------------------------------------------------------------
- X * ftw:
- X * Entry point to do the search, ftw is a front end
- X * to the recursive fwt1.
- X * ftw() places some of the arguments to global variables
- X * so that they arguments would not have to be passed around to
- X * ftw1().
- X *
- X */
- X
- Xftw(f,fn,depth)
- Xchar *f;
- Xint (*fn)();
- Xint depth;
- X{
- X char *p;
- X struct stat statbuf;
- X int i;
- X
- X strcpy(filename,f);
- X if( filename[ strlen(filename)-1 ] != '/' ) {
- X filename[ strlen(f) ] = '/';
- X filename[ strlen(f)+1 ] = '\0';
- X }
- X func=fn;
- X
- X if( lstat(f,&statbuf) < 0 ) return(-1);
- X
- X (*func)(f,&statbuf);
- X
- X if( isproper( statbuf.st_mode ) ) fwt1(depth);
- X
- X return(0);
- X}
- X
- X/* ----------------------------------------------------------------------
- X * fwt1:
- X * 2 versions of this routine currently live here:
- X * XENIX/SYSV, and SUN/BSD. They both differ in
- X * the manner in which they access directories.
- X * Any chnages needed to work on another system
- X * should only have to made for this routine.
- X *
- X * Below is the SUN/BSD version of fwt1()
- X * --------------------------------------
- X *
- X */
- X
- X#if SUN || BSD
- X
- Xstatic fwt1(depth)
- Xint depth;
- X{
- X
- X#if SUN
- X DIR *dirp;
- X struct dirent *dp;
- X#else
- X DIR *dirp;
- X struct direct *dp;
- X#endif
- X char *basep;
- X struct stat statbuf;
- X
- X if( !depth ) return;
- X basep=filename+strlen(filename);
- X
- X dirp=opendir(filename);
- X if( dirp == NULL ) return;
- X for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- X if( dp->d_name[0]=='.' && dp->d_name[1]=='\0' ) continue;
- X if( dp->d_name[0]=='.' && dp->d_name[1]=='.' &&
- X dp->d_name[2]=='\0' ) continue;
- X strcpy(basep,dp->d_name);
- X if( lstat(filename,&statbuf) < 0 ) continue;
- X (*func)(filename,&statbuf);
- X if( isproper( statbuf.st_mode ) ) {
- X basep[ strlen(dp->d_name) ] = '/';
- X basep[ strlen(dp->d_name)+1 ] = '\0';
- X fwt1(depth-1);
- X }
- X }
- X closedir(dirp);
- X *basep = '\0';
- X}
- X#endif
- X
- X/* ----------------------------------------------------------------------
- X * ftw1:
- X * This function does the samething as ftw1() above, but is
- X * meant for XENIX/SYSV type systems that do directory reading
- X * "by hand"
- X *
- X * Below is the XENIX/SYSV version of fwt1()
- X * --------------------------------------
- X */
- X
- X#if XENIX || SYSV
- X
- Xstatic fwt1(depth)
- Xint depth;
- X{
- X char *basep;
- X FILE *dirp;
- X struct direct dp;
- X struct stat statbuf;
- X int count;
- X
- X if( !depth ) return;
- X
- X basep=filename+strlen(filename);
- X dirp=fopen(filename,"r");
- X if( dirp == NULL ) return;
- X for(count = fread(&dp,sizeof(struct direct),1,dirp); count;
- X count = fread(&dp,sizeof(struct direct),1,dirp) ) {
- X
- X if( dp.d_name[0]=='.' && dp.d_name[1]=='\0' ) continue;
- X if( dp.d_name[0]=='.' && dp.d_name[1]=='.' &&
- X dp.d_name[2]=='\0' ) continue;
- X strcpy(basep,dp.d_name);
- X if( lstat(filename,&statbuf) < 0 ) continue;
- X (*func)(filename,&statbuf);
- X if( isproper( statbuf.st_mode ) ) {
- X basep[ strlen(dp.d_name) ] = '/';
- X basep[ strlen(dp.d_name)+1 ] = '\0';
- X fwt1(depth-1);
- X }
- X }
- X fclose(dirp);
- X *basep = '\0';
- X}
- X
- X#endif
- END_OF_FILE
- if test 5549 -ne `wc -c <'rhdir.c'`; then
- echo shar: \"'rhdir.c'\" unpacked with wrong size!
- fi
- # end of 'rhdir.c'
- fi
- if test -f 'rhparse.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rhparse.c'\"
- else
- echo shar: Extracting \"'rhparse.c'\" \(10196 characters\)
- sed "s/^X//" >'rhparse.c' <<'END_OF_FILE'
- X
- X/* ----------------------------------------------------------------------
- X * FILE: rhparse.c
- X * (c) 1989 Ken Stauffer
- X * This contains the parser for the C expressions,
- X * gettoken(), getit() and ungetit() routines.
- X * sectime(), datespec(), expression(), expr(), exp0(), ... , factor()
- X * locatename(), push(), find_macro()
- X *
- X *
- X * ---------------------------------------------------------------------- */
- X
- X#include "rh.h"
- X#include <ctype.h>
- X#include <pwd.h>
- X
- Xstatic int cpos; /* current character position */
- X
- X/* ----------------------------------------------------------------------
- X * getit:
- X * Return the next character, input of from a file or
- X * a string.
- X */
- X
- Xgetit()
- X{
- X cpos++;
- X if( dashe ) return( (*expstr) ? *expstr++ : EOF );
- X else return( getc(expfile) );
- X}
- X
- X/* ----------------------------------------------------------------------
- X * ungetit:
- X * Unget a char.
- X *
- X */
- X
- Xungetit(c)
- Xint c;
- X{
- X cpos--;
- X if( dashe ) expstr = (*expstr) ? expstr-1 : expstr;
- X else ungetc(c,expfile);
- X}
- X
- X/* ----------------------------------------------------------------------
- X * error:
- X * Print an error message an quit.
- X */
- X
- Xerror(s)
- Xchar *s;
- X{
- X if( dashf )
- X fprintf(stderr,"File: %s, ",expstr);
- X else if( dashe )
- X fprintf(stderr,"argv[%d], ",dashe);
- X else
- X fprintf(stderr,"File: stdin, ");
- X
- X fprintf(stderr,"char: %d, %s\n",cpos,s);
- X exit(-1);
- X}
- X
- X/* ----------------------------------------------------------------------
- X * push:
- X * "assemble" the instruction into the StackProgram[] array.
- X *
- X */
- X
- Xpush(t,val)
- Xlong t,val;
- X{
- X if( PC >= LENGTH ) error("no more space for expression!");
- X StackProgram[PC].i_type=t;
- X StackProgram[PC++].i_value=val;
- X return(PC-1);
- X}
- X
- X/* ----------------------------------------------------------------------
- X * find_macro:
- X * Routine consumes the input file until it reaches the
- X * macro name followed by a colon. If EOF
- X * is encountered first then the program quits.
- X *
- X */
- X
- Xfind_macro()
- X{
- X while( token != MACRONAME && token != EOF ) token = gettoken();
- X if( token == EOF ) error("macro name not found");
- X token = gettoken();
- X if( token != COLON ) error("missing ':' after macro name");
- X token = gettoken();
- X}
- X
- X/* ----------------------------------------------------------------------
- X * expression()
- X * Parse an expression.
- X * This routine calls exp() and exp() calls exp0() and so on...
- X * If the -m option was specified then the routine find_macro()
- X * is called.
- X * The NOW constant is initialized here.
- X *
- X */
- X
- Xexpression()
- X{
- X PC = 0; cpos = 0;
- X constants[ NOW_INDEX ] = time(0);
- X token = gettoken();
- X if( dashm ) find_macro();
- X expr();
- X if( token!= ';' && token!= EOF ) error("missing ';' or EOF");
- X push(0,0); /* NULL terminated the program */
- X}
- X
- X/* OPERATOR ?: */
- Xexpr()
- X{
- X int qm,colon,nop;
- X
- X expr0();
- X if( token == QM ) {
- X token = gettoken();
- X qm = push(QM,0);
- X expr();
- X if( token != COLON ) error("missing ':'");
- X token = gettoken();
- X colon = push(COLON,0);
- X expr();
- X nop = push(NOP,0); /* nop */
- X
- X StackProgram[qm].i_value = colon;
- X StackProgram[colon].i_value = nop;
- X }
- X}
- X
- X/* OPERATOR || */
- Xexpr0()
- X{
- X expr1();
- X for(;;)
- X if( token == OR ) {
- X token = gettoken();
- X expr1();
- X push(OR,0);
- X } else break;
- X}
- X
- X/* OPERATOR && */
- Xexpr1()
- X{
- X expr2();
- X for(;;)
- X if( token == AND ) {
- X token = gettoken();
- X expr2();
- X push(AND,0);
- X } else break;
- X}
- X
- X/* OPERATOR | */
- Xexpr2()
- X{
- X expr3();
- X for(;;)
- X if( token == BOR ) {
- X token = gettoken();
- X expr3();
- X push(BOR,0);
- X } else break;
- X}
- X
- X/* OPERATOR ^ */
- Xexpr3()
- X{
- X expr4();
- X for(;;)
- X if( token == BXOR ) {
- X token = gettoken();
- X expr4();
- X push(BXOR,0);
- X } else break;
- X}
- X
- X/* OPERATOR & */
- Xexpr4()
- X{
- X expr5();
- X for(;;)
- X if( token == BAND ) {
- X token = gettoken();
- X expr5();
- X push(BAND,0);
- X } else break;
- X}
- X
- X/* OPERATOR == != */
- Xexpr5()
- X{
- X int t;
- X expr6();
- X for(;t=token;)
- X if( t==EQ || t==NE ) {
- X token = gettoken();
- X expr6();
- X push(t,0);
- X } else break;
- X}
- X
- X/* OPERATOR < <= > >= */
- Xexpr6()
- X{
- X int t;
- X expr7();
- X for(;t=token;)
- X if( t==LE || t==GE || t==GT || t==LT ) {
- X token = gettoken();
- X expr7();
- X push(t,0);
- X } else break;
- X}
- X
- X/* OPERATOR << >> */
- Xexpr7()
- X{
- X int t;
- X expr8();
- X for(;t=token;)
- X if( t==SHIFTL || t==SHIFTR ) {
- X token = gettoken();
- X expr8();
- X push(t,0);
- X } else break;
- X}
- X
- X/* OPERATOR + - */
- Xexpr8()
- X{
- X int t;
- X expr9();
- X for(;t=token;)
- X if( t==PLUS || t==MINUS ) {
- X token = gettoken();
- X expr9();
- X push(t,0);
- X } else break;
- X}
- X
- X/* OPERATOR * / % */
- Xexpr9()
- X{
- X int t;
- X expr10();
- X for(;t=token;)
- X if( t==MUL || t==DIV || t==MOD ) {
- X token = gettoken();
- X expr10();
- X push(t,0);
- X } else break;
- X}
- X
- X/* OPERATOR ~ ! - */
- Xexpr10()
- X{
- X int t;
- X t = token;
- X if( t==NOT || t==BNOT || t==MINUS ){
- X token = gettoken();
- X expr10();
- X push((t==MINUS)? UNIMINUS : t ,0);
- X } else factor();
- X}
- X
- X/* ----------------------------------------------------------------------
- X * factor:
- X * Parse a factor. Could be a number, variable or
- X * string.
- X */
- X
- Xfactor()
- X{
- X long l,datespec();
- X
- X switch(token) {
- X case '(':
- X token = gettoken();
- X expr();
- X if( token != ')' )
- X error("missing ')'");
- X token = gettoken();
- X break;
- X case NUMBER:
- X push(NUMBER,tokenval);
- X token = gettoken();
- X break;
- X case FIELD:
- X push(FIELD,tokenval);
- X token = gettoken();
- X break;
- X case '[':
- X token = gettoken();
- X l=datespec();
- X if( token != ']' )
- X error("missing ']'");
- X token = gettoken();
- X push(NUMBER,l);
- X break;
- X case STAR:
- X push(STAR,tokenval);
- X token = gettoken();
- X break;
- X default:
- X error("syntax error");
- X }
- X}
- X
- X/* ----------------------------------------------------------------------
- X * sectime:
- X * calculate the number of seconds between January 1, 1970
- X * and year/month/day. Return that value.
- X *
- X */
- X
- X#define leap(d) (((d % 4 == 0) && (d % 100 != 0)) || (d % 400 == 0))
- X#define DAYSEC (3600*24)
- X#define YERSEC (3600*24*365)
- X#define TIME0 1970
- X
- Xlong sectime(year,month,day)
- Xint year,month,day;
- X{
- X
- X static int months[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
- X int yeardays,leapers,x;
- X long seconds;
- X
- X if(month>12 || month<1 || year<TIME0 || day<1 || day>months[month]+
- X (month==2 && leap(year)) )
- X return(-1);
- X
- X yeardays = leapers = 0;
- X
- X for(x=1;x<month;x++)
- X yeardays += months[x];
- X if ((month > 2) && leap(year)) yeardays++;
- X
- X for(x=TIME0; x<year; x++)
- X if(leap(x)) leapers++;
- X
- X seconds = yeardays*DAYSEC+(year-TIME0)*YERSEC+7*3600+
- X leapers*DAYSEC + day*DAYSEC;
- X
- X return(seconds);
- X
- X}
- X
- X/* ----------------------------------------------------------------------
- X * datespec:
- X * parse a date. Return the number of seconds from
- X * some date in 1970, until the specified date.
- X */
- X
- Xlong datespec()
- X{
- X int year,month,day,seconds;
- X
- X if( token != NUMBER ) error("number expected");
- X year = tokenval;
- X token = gettoken();
- X if( token != DIV ) error("missing '/'");
- X token = gettoken();
- X if( token != NUMBER ) error("number expected");
- X month = tokenval;
- X token = gettoken();
- X if( token != DIV ) error("missing '/'");
- X token = gettoken();
- X if( token != NUMBER ) error("number expected");
- X day = tokenval;
- X token = gettoken();
- X
- X if( (seconds = sectime(year,month,day)) < 0 )
- X error("invalid date");
- X
- X return(seconds);
- X}
- X
- X
- X/* ----------------------------------------------------------------------
- X * locatename:
- X * Does a linear seach for 's' in the array 'identifiers[]'.
- X *
- X */
- X
- Xlocatename(s)
- Xchar *s;
- X{
- X register int i;
- X
- X for(i=0; identifiers[i]; i++ )
- X if( !strcmp(s,identifiers[i]) ) return(i);
- X return(-1);
- X}
- X
- X/* ----------------------------------------------------------------------
- X * gettoken:
- X * Return the next token.
- X * global variable: tokenval will contain any extra
- X * attribute associated with the returned token, ie
- X * the VALUE of a number, the index of the string etc...
- X *
- X */
- X
- Xgettoken()
- X{
- X char buf[IDLENGTH+1],*bufp=buf;
- X int c;
- X
- X for(;;) {
- X while( (c=getit()) == ' ' || c=='\n' || c=='\t' );
- X if( c == '#' ) while( (c=getit())!= '\n' && c!= EOF );
- X else break;
- X }
- X
- X if(c=='0') {
- X tokenval=0;
- X while( ( c=getit() ) >= '0' && c <= '7' ) {
- X tokenval <<= 3;
- X tokenval += c-'0';
- X }
- X if( isdigit(c) ) error("bad octal constant");
- X ungetit(c);
- X return(NUMBER);
- X }
- X
- X if(isdigit(c)) {
- X tokenval=c-'0';
- X while(isdigit( (c=getit()) )) {
- X tokenval *=10;
- X tokenval += c-'0';
- X }
- X ungetit(c);
- X return(NUMBER);
- X }
- X
- X if(isalpha(c)) {
- X int count=0,index;
- X do {
- X if(count++ < IDLENGTH) *bufp++ = c;
- X c=getit();
- X } while( isalnum(c) );
- X ungetit(c);
- X *bufp='\0';
- X if( (index=locatename(buf)) < 0 ) return(UNKNOWN);
- X tokenval = constants[index];
- X if( index==MACRO_INDEX ) return(MACRONAME);
- X return( ( isupper( *(identifiers[index]) ) ? NUMBER : FIELD ) );
- X }
- X
- X if( c == '"' ) {
- X int index,st=0;
- X index=starfree;
- X while( (c=getit())!= '"' ) {
- X if( starfree > STARLEN )
- X error("no more string space");
- X if(c=='*') st++;
- X if(st>1) error("too many *'s present");
- X Starbuf[starfree++]=c;
- X }
- X Starbuf[starfree++]='\0';
- X tokenval=index;
- X return(STAR);
- X }
- X
- X if( c == '=' ) {
- X c=getit();
- X if(c== '=') return(EQ);
- X else {
- X ungetit(c);
- X return('=');
- X }
- X }
- X
- X if( c== '$' ) {
- X int count=0;
- X struct passwd *info,*getpwnam();
- X c=getit();
- X do {
- X if (count++ < IDLENGTH) *bufp++ = c;
- X c=getit();
- X } while( isalnum(c) );
- X ungetit(c);
- X *bufp='\0';
- X info=getpwnam(buf);
- X if(info == NULL)
- X error("unknown user name after $");
- X tokenval = info->pw_uid;
- X return( NUMBER );
- X }
- X
- X if( c == '!' ) {
- X c=getit();
- X if( c == '=' ) return(NE);
- X ungetit(c);
- X return(NOT);
- X }
- X
- X if( c == '>' ) {
- X c=getit();
- X if( c == '=' ) return(GE);
- X if( c == '>' ) return(SHIFTR);
- X ungetit(c);
- X return(GT);
- X }
- X
- X if( c == '<' ) {
- X c=getit();
- X if( c == '=' ) return(LE);
- X if( c == '<' ) return(SHIFTL);
- X ungetit(c);
- X return(LT);
- X }
- X
- X if( c == '&' ) {
- X c=getit();
- X if( c == '&' ) return(AND);
- X ungetit(c);
- X return(BAND);
- X }
- X
- X if( c == '|' ) {
- X c=getit();
- X if( c == '|' ) return(OR);
- X ungetit(c);
- X return(BOR);
- X }
- X if( c == '^' ) return(BXOR);
- X if( c == '+' ) return(PLUS);
- X if( c == '-' ) return(MINUS);
- X if( c == '*' ) return(MUL);
- X if( c == '/' ) return(DIV);
- X if( c == '%' ) return(MOD);
- X if( c == '~' ) return(BNOT);
- X if( c == '?' ) return(QM);
- X if( c == ':' ) return(COLON);
- X
- X return(c);
- X}
- X
- END_OF_FILE
- if test 10196 -ne `wc -c <'rhparse.c'`; then
- echo shar: \"'rhparse.c'\" unpacked with wrong size!
- fi
- # end of 'rhparse.c'
- fi
- if test -f 'rh.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rh.man'\"
- else
- echo shar: Extracting \"'rh.man'\" \(6020 characters\)
- sed "s/^X//" >'rh.man' <<'END_OF_FILE'
- X.TH RH 1
- X.SH NAME
- Xrh - recursive file locater (rawhide)
- X.SH SYNOPSIS
- X.BI "rh [-rlha] [-f" " filename" " [-m" "name" "] | -e" " expression"
- X.BI "] [" "file" " ...]"
- X.SH DECRIPTION
- X.I Rh
- Xrecursively searches the file system starting at
- X.I file ...
- Xfor files that make a C expression true. If no
- X.I files
- Xare listed then the current working directory is used.
- X.PP
- XExpressions for
- X.I rh
- Xcan come from the command line, a file, or from
- Xstandard input (if no
- X.I -e
- Xor
- X.I -f
- Xoptions are given).
- XThe basic form of a
- X.I rh
- Xexpression consists of a valid C expression containing
- Xinteger constants and variables.
- X.PP
- X.I Constants
- X, are either numeric or symbolic. Symbolic constants refer
- Xto the #define's in the file
- X.I /usr/include/sys/stat.h.
- XOnly the useful constants are implemented. All symbolic
- Xconstants are UPPER CASE and the "S_" prefix from the
- Xsymbol name is omitted.
- X.PP
- X.I Variables
- X, are lower case symbols that specify a field in the
- Xstat structure (eg. st_size,st_mode ). For each file examined by
- X.I rh
- Xthese internal varibles are updated to match the current
- Xfile. For convienience the "st_" prefix is dropped from variable
- Xnames.
- X.SH OPTIONS
- X.B Rh
- Xoptions can appear in any order, multiple options can
- Xbe together within the same argument. However
- Xno options may occur
- X.I after
- Xthe filename list is given.
- X.IP -r
- XThis option
- X.B disables
- X.I rh
- Xfrom recursively searching for files.
- X.PP
- X.IP -l
- XNormally
- X.I rh
- Xprints each matching filename on a line by itself. However,
- X.I -l
- Xwill cause filenames to be displayed with permission modes and
- Xthe file size. Filename printing is similar to that of the
- X.I ls
- X(1) command.
- X.PP
- X.IP -h
- XThis tells
- X.I rh
- Xto display a useful help message. The message
- Xexplains the command line usage, a list of
- Xavailable constants/variables and a list
- Xof valid operators.
- X.I Rh
- Xthen continues as though the
- X.I -h
- Xoption was not present.
- X.PP
- X.IP -f
- XExpects that the next argument will be the
- X.I filename
- Xof a file containing a
- X.I rh
- Xexpression. It is an error to have both the
- X.I -f
- Xand
- X.I -e
- Xoptions together. Expressions should appear
- Xin
- X.I filename
- Xin the same manner as expressions that are
- Xentered interactively. The
- X.I -m
- Xoption expands this to allow labels to appear in the file.
- XSee
- X.I -m
- Xfor more details.
- X.PP
- X.IP -m
- XIs followed immediatly by a
- X.I macroname
- Xwhich specifies the starting location of a
- X.I rh
- Xexpression within the file
- X.I filename.
- XA ':' must appear after
- X.I macroname.
- XFor example:
- X.PP
- X.RS 8
- Xwritable:
- X.RS 5
- X(mode & 022) && (uid == $joe );
- X.PP
- X.RE
- X.RE
- X.IP
- XA
- X.I -mwritable
- Xoption would cause the expression following
- X.I writeable:
- Xto be used as the
- X.I rh
- Xexpression.
- X.PP
- X.IP -e
- XThis option takes the next argument as the
- X.I rh
- X.I expression
- Xthat will be used for the file search. Since many
- Xof the operators are also
- X.I sh
- X(1) meta characters and since expressions may have
- Xspaces in them, it is strongly recommended that the
- X.I expression
- Xbe enclosed in ''.
- X.PP
- X.IP -a
- XThis option
- X.I adds
- Xmore information to the long output of the
- X.I -l
- Xoption. Information such as uid, gid, and last modified date
- Xare output. The
- X.I -a
- Xoption implies the
- X.I -l
- Xoption.
- X.PP
- X.SH USAGE
- X.SS "The following are the valid constants:"
- X.IP NOW
- XThis constant is set to the current time at the start of
- X.I rh.
- XIt is used to make comparisons with atime,ctime and mtime.
- X.PP
- X.I
- XIFBLK IFDIR IFLNK IFMT IFREG IFSOCK ISGID ISUID ISVTX -
- Xsee stat(2).
- X.PP
- X.SS "The following are the valid variables:"
- X.PP
- X.I
- Xatime ctime dev gid ino mode mtime nlink rdev size uid -
- Xsee stat(2).
- X.PP
- X.SS "Valid C operators are:"
- X.PP
- X! ~ - * / % + < <= > >= == != & ^ | << >> && || ?:
- X.PP
- XOperator precedence, associativity and semantics are idenitical
- Xto C.
- X.PP
- X.SS "Special operators:"
- X.PP
- X.IP $username
- XThis operater evaluates to the integer uid of
- X.I username.
- X.PP
- X.IP """*.c"""
- XThis operator evaluates to true if the current filename matches
- X"expression". The only form of
- X.I expression
- Xsupported is, "filename", "*filename", "filename*", "*".
- XWhen doing comparisons, only the base name is examined, not
- Xpathnames.
- X.PP
- X.IP [yyyy/mm/dd]
- XThe date enclosed in the [], will evaluate to a numeric
- Xquantity suitable for comparing with atime,mtime or ctime.
- XThe year cannot be abbreviated to say, 89 for 1989.
- X.PP
- X.IP NOTE:
- XThat the
- X.I special operators
- Xtake on higher precedence than the C operators.
- X.PP
- X.SS "Lexical conventions:"
- X.PP
- XNumbers may be entered in octal by preceeding it with
- Xa leading zero. Otherwise the number is taken to be
- Xdecimal.
- X.PP
- X.PP
- XAll characters after a '#' symbol are ignored upto a
- Xnewline or end of file. This allows for comments
- Xin rh expression files.
- X.PP
- XAn expression may be terminated by either
- Xa ';' or EOF.
- X.PP
- X.SH EXAMPLES
- XThe following are examples of
- X.I rh
- Xexpression. All expressions may appear in either a file,
- Xinteractively, or on the command line:
- X.PP
- X.RS 8
- X(mode & 022) && (uid == $joe );
- X.PP
- X.RE
- XMatches all files that have uid equal to username 'joe' and
- Xis writable by other people.
- X.PP
- X.RS 8
- X!uid && (mode & ISUID ) && (mode & 02);
- X.PP
- X.RE
- XMatches all files that are owned by root (uid==0) and that
- Xhave set-uid on execution bit set, and is writable.
- X.PP
- X.RS 8
- X(size > 10*1024) && (mode & 0111) && (atime <= NOW-24*3600);
- X.PP
- X.RE
- XThis expression finds all executable files greater than 10K, that
- Xhave not been executed in the last 24 hours.
- X.PP
- X.RS 8
- Xsize < ( ("*.c") ? 4096 : 32*1024 );
- X.PP
- X.RE
- XThis cryptic expression finds C source files less than 4K, or
- Xwill find other files if they are smaller than 32K. No other files
- Xwill match.
- X.PP
- X.RS 8
- X!(size % 1024);
- X.PP
- X.RE
- XMatches files that are a multiple of 1K.
- X.PP
- X.RS 8
- Xmtime >= [1982/3/1] && mtime <= [1982/3/31];
- X.PP
- X.RE
- XThis exression finds files that were modified during the
- Xmonth of march, in the year 1982.
- X.PP
- X.SH SEE ALSO
- Xsh(1), find(1), stat(2), ls(1), chmod(1)
- X.PP
- XThe C programming language.
- X.SH AUTHOR
- XKen Stauffer (University of Calgary)
- X.PP
- Xstauffer@sixk
- X.PP
- X.SH BUGS
- XThe date operator should also allow for time to be entered.
- XFull regular exressions should be allowed within the " " operator.
- X.PP
- END_OF_FILE
- if test 6020 -ne `wc -c <'rh.man'`; then
- echo shar: \"'rh.man'\" unpacked with wrong size!
- fi
- # end of 'rh.man'
- fi
- if test -f 'sample' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sample'\"
- else
- echo shar: Extracting \"'sample'\" \(553 characters\)
- sed "s/^X//" >'sample' <<'END_OF_FILE'
- X# This file contains 'rh' expressions.
- X# '#' character causes the rest of the line to
- X# be ignored...
- X#
- X
- X# ex1, ex2, ex3, ex4, ex5 come from the manual...
- X#
- Xex1:
- X (mode & 022) && (uid == $uucp );
- X
- Xex2:
- X !uid && (mode & ISUID ) && (mode & 02);
- X
- Xex3:
- X (size > 10*1024) && (mode & 0111) && (atime <= NOW-24*3600);
- X
- Xex4:
- X size < (("*.c") ? 4096 : 32*1024);
- X
- Xex5:
- X !(size % 1024);
- X
- X# find files that have been created in the last hour.
- X#
- Xnew:
- X ctime > NOW-3600;
- X
- X# find files who have not been modified in the last 30 days.
- X#
- Xaged:
- X mtime < NOW-30*24*3600;
- X
- END_OF_FILE
- if test 553 -ne `wc -c <'sample'`; then
- echo shar: \"'sample'\" unpacked with wrong size!
- fi
- # end of 'sample'
- fi
- echo shar: End of shell archive.
- exit 0
-
-